package listo.client;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import listo.utils.logging.Log;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

@Singleton
public class Executors {

    private final ExecutorService contextExecutor = java.util.concurrent.Executors
            .newSingleThreadExecutor(new ThreadFactory() {
                public Thread newThread(Runnable r) {
                    return new Thread(r, "context");
                }
            });

    private final ExecutorService saverExecutor = java.util.concurrent.Executors
            .newSingleThreadExecutor(new ThreadFactory() {
                public Thread newThread(Runnable r) {
                    return new Thread(r, "saver");
                }
            });

    private final ScheduledExecutorService reminderExecutor = java.util.concurrent.Executors
            .newSingleThreadScheduledExecutor(new ThreadFactory() {
                public Thread newThread(Runnable r) {
                    return new Thread(r, "reminder");
                }
            });

    private final ScheduledExecutorService cleanupExecutor = java.util.concurrent.Executors
            .newSingleThreadScheduledExecutor(new ThreadFactory() {
                public Thread newThread(Runnable r) {
                    return new Thread(r, "cleanup");
                }
            });

    private final Log log;
    private final AppConfig appConfig;

    @Inject
    public Executors(Log log, AppConfig appConfig) {
        this.log = log;
        this.appConfig = appConfig;
    }

    public ExecutorService getContextExecutor() {
        return contextExecutor;
    }

    public ExecutorService getSaverExecutor() {
        return saverExecutor;
    }

    public ScheduledExecutorService getReminderExecutor() {
        return reminderExecutor;
    }

    public ScheduledExecutorService getCleanupExecutor() {
        return cleanupExecutor;
    }

    public void shutdown() throws Exception {
        log.debug("Stopping all background threads");

        ExecutorService[] executors = new ExecutorService[] {
                cleanupExecutor,
                reminderExecutor,
                saverExecutor,
                contextExecutor
        };

        for (ExecutorService executor : executors) {
            executor.shutdown();
        }
        for (ExecutorService executor : executors) {
            executor.awaitTermination(appConfig.getExecutorsTerminationTimeout(), TimeUnit.MILLISECONDS);
        }
    }

}
